package cn.xshi.route.publisher;

import cn.xshi.route.vo.ChannelEntity;
import cn.xshi.route.vo.RequestInfo;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.*;
import io.netty.util.CharsetUtil;
import cn.xshi.common.util.JsonUtil;
import lombok.extern.slf4j.Slf4j;

/**
 * @Desc 服务端网关路由处理器
 * @Author 邓纯杰
 * @CreateTime 2012-12-12 12:12:12
 */
@Slf4j
public class GatewayNettyServerHandler extends ChannelInboundHandlerAdapter{

    GatewayChannelUtil gatewayChannelUtil;

    public GatewayNettyServerHandler(){

    }

    public GatewayNettyServerHandler(GatewayChannelUtil channelUtil){
        this.gatewayChannelUtil = channelUtil;
    }

    /**
     * 客户端连接会触发
     */
    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        log.info("Channel active......");
    }

    /**
     * 客户端发消息会触发
     */
    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        log.info("网关路由 Received message from client : {}", msg.toString());
        RequestInfo requestInfo = JsonUtil.fromAliFastJson(msg.toString(), RequestInfo.class);
        if(requestInfo.isShakeHands()){//初次握手
            this.gatewayChannelUtil.add(ctx.channel());
            ChannelEntity channelEntity = new ChannelEntity(ctx.channel(),requestInfo.getClientGroupId(),requestInfo.getClientId(),requestInfo);
            boolean res1 = this.gatewayChannelUtil.putChannel(ctx.channel().id().asLongText(),channelEntity);
            if(res1){
                log.info("网关路由 Channel"+ctx.channel().id().asLongText()+"加入到缓存中成功......");
            }else{
                log.info("网关路由 Channel"+ctx.channel().id().asLongText()+"加入到缓存中失败......");
            }
            boolean res = this.gatewayChannelUtil.put(requestInfo.getClientGroupId(),channelEntity);
            if(res){
                log.info("网关路由 通道号"+ctx.channel().id().asLongText()+"加入到缓存中成功......");
            }else{
                log.info("网关路由 通道号"+ctx.channel().id().asLongText()+"加入到缓存中失败......");
            }
        }
        //创建一个持有数据的ByteBuf
        ByteBuf buf = Unpooled.copiedBuffer(msg.toString(), CharsetUtil.UTF_8);
        //数据冲刷
        ChannelFuture cf = ctx.writeAndFlush(buf);
        //添加ChannelFutureListener以便在写操作完成后接收通知(握手反馈)
        cf.addListener(new ChannelFutureListener() {
            @Override
            public void operationComplete(ChannelFuture future) throws Exception {
                if (future.isSuccess()){
                    log.info("路由服务与网关路由握手反馈成功...");
                }else{
                    log.info("路由服务与网关路由握手反馈失败...");
                    future.cause().printStackTrace();
                }
            }
        });
//        ctx.write(msg.toString());//握手反馈
//        ctx.flush();
    }

    /**
     * 发生异常触发
     */
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        cause.printStackTrace();
        ctx.close();
    }

    /**
     * 客户端连接之后获取客户端channel并放入group中管理
     * @param ctx
     * @throws Exception
     */
    @Override
    public void handlerAdded(ChannelHandlerContext ctx) throws Exception {
        super.handlerAdded(ctx);
        Channel channel = ctx.channel();
        log.info("网关路由有通道号连接进来......"+channel.id().asLongText());
    }

    /**
     * 移除对应客户端的channel
     * @param ctx
     * @throws Exception
     */
    @Override
    public void handlerRemoved(ChannelHandlerContext ctx) throws Exception {
        super.handlerRemoved(ctx);
        log.info("网关路由通道号"+ctx.channel().id().asLongText()+"离线......");
        Channel channel = ctx.channel();
        boolean res = this.gatewayChannelUtil.delete(channel);
        if(res){
            log.info("从网关路由通道组中移除通道号："+channel.id().asLongText()+"成功！");
            ChannelEntity channelEntity = this.gatewayChannelUtil.getChannel(channel.id().asLongText());
            //移除
            res = this.gatewayChannelUtil.removeChannel(channel.id().asLongText());
            if(res){
                log.info("从网关路由Channel缓存中移除通道号："+channel.id().asLongText()+"成功！");
            }else{
                log.info("从网关路由Channel缓存中移除通道号："+channel.id().asLongText()+"失败！");
            }
            if(null != channelEntity){
                res = this.gatewayChannelUtil.remove(channelEntity.getClientGroupId(),channelEntity.getClientId());
            }
            if(res){
                log.info("从网关路由缓存中移除通道号："+channel.id().asLongText()+"成功！");
            }else{
                log.info("从网关路由缓存中移除通道号："+channel.id().asLongText()+"失败！");
            }
        }else{
            log.info("从网关路由通道组中移除通道号："+channel.id().asLongText()+"失败！");
        }
    }
}
